package com.nostra13.example.universalimageloader;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AbsListView;

import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener;

/**
 * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
 */
public class ImageGridActivity extends BaseActivity {

	private List<String> imageUrls;
	private List<String> previewImageUrls;
	private ProgressBar previewLoadingSpinner;
	private ProgressBar newPhotosLoadingSpinner;
	private TextView noConnectTextView;
	private DisplayImageOptions options;
	private ImageAdapter imageAdapter;
	private GridView gridView;
	private DownloadPreviewImagesTask downloadPreviewImagesTask;
	private static String DOWNLOAD_TASK= "download_task";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.ac_image_grid);
		/*previewLoadingSpinner = (ProgressBar) findViewById(R.id.preview_img_loading);
		newPhotosLoadingSpinner = (ProgressBar) findViewById(R.id.new_photos_loading);*/
		noConnectTextView = (TextView) findViewById(R.id.no_connect_message);
		
		if (getLastNonConfigurationInstance() != null) { 
			
			Map<String, Object> retainedObjs = (Map<String, Object>) getLastNonConfigurationInstance();
			imageUrls = (List<String>) retainedObjs.get(ImageExtractor.ORIGINAL_IMAGES);
			previewImageUrls = (List<String>) retainedObjs.get(ImageExtractor.PREVIEW_IMAGES);
			initGridView();
			downloadPreviewImagesTask = (DownloadPreviewImagesTask) retainedObjs.get(DOWNLOAD_TASK);
			if (downloadPreviewImagesTask != null && downloadPreviewImagesTask.getStatus() == AsyncTask.Status.RUNNING) {
				downloadPreviewImagesTask.attachActivity(this);
				downloadPreviewImagesTask.setSpinnerVisible();
				//((ProgressBar) findViewById(R.id.new_photos_loading)).setVisibility(View.VISIBLE);
    		} else {
    			Log.d("downloadPreviewImagesTask", "downloadPreviewImagesTask has executed already");
    		}
			
			//imageAdapter.notifyDataSetChanged();
		}
		else {
			imageUrls = new ArrayList<String>();
			previewImageUrls = new ArrayList<String>();
			downloadPreviewImagesTask = getDownloadPreviewImagesTask(R.id.preview_img_loading, getText(R.string.gallery_url).toString());
		}
		
		
	}
	
	private DownloadPreviewImagesTask getDownloadPreviewImagesTask(int spinnerID, String url) {
		downloadPreviewImagesTask = new DownloadPreviewImagesTask();
		downloadPreviewImagesTask.setSpinner(spinnerID);
		downloadPreviewImagesTask.attachActivity(this);
		downloadPreviewImagesTask.execute(url); // show spinner
		return downloadPreviewImagesTask;
	}
	
	public Object onRetainNonConfigurationInstance() {
	    Map<String, Object> objsToRetain = new HashMap<String, Object>(2);
	    objsToRetain.put(ImageExtractor.PREVIEW_IMAGES, previewImageUrls);
	    objsToRetain.put(ImageExtractor.ORIGINAL_IMAGES, imageUrls);
	    objsToRetain.put(DOWNLOAD_TASK, downloadPreviewImagesTask);
		return objsToRetain;
	}
	
	class EndlessListListener implements OnScrollListener {

		private int lastVisiblePosition;
		private int firstVisiblePosition;
		
		public void onScroll(AbsListView view, int firstVisible, int visibleCount, int totalCount) {}
		
	    @Override
	    public void onScrollStateChanged(AbsListView view, int scrollState) {
	    	GridView gview = (GridView)view;

	    	if (scrollState == SCROLL_STATE_IDLE && // while scrolling variable scrollState can be - SCROLL_STATE_IDLE and SCROLL_STATE_TOUCH_SCROLL
	    			lastVisiblePosition == gview.getLastVisiblePosition() && // lastVisiblePosition is not change since last scroll
	    			firstVisiblePosition == gview.getFirstVisiblePosition() && // firstVisiblePosition is not change since last scroll
	    			gview.getLastVisiblePosition() == gview.getCount() - 1 // scroll pointer is located at the end of the grid
	    			) {
	    		Log.d("loadData", "new data loaded");
	    		String photosUri = ImageExtractor.PHOTOS_URI;
	    		String url = getText(R.string.gallery_url).toString() + photosUri.replace(ImageExtractor.FROM_REPLACEMENT, String.valueOf(previewImageUrls.size()));;
	    		Log.d("url", url);
	    		if (downloadPreviewImagesTask != null && downloadPreviewImagesTask.getStatus() == AsyncTask.Status.RUNNING) {
	    			Log.d("downloadPreviewImagesTask", "downloadPreviewImagesTask is running");
	    		} else {
	    			downloadPreviewImagesTask = getDownloadPreviewImagesTask(R.id.new_photos_loading, url);
	    		}
	    	}
	    	firstVisiblePosition = gview.getFirstVisiblePosition();
	    	lastVisiblePosition = gview.getLastVisiblePosition();
	    }
	}
	
	class DownloadPreviewImagesTask extends AsyncTask<String, Void, Map<String, String>> {
        
		private Exception exc = null;
		private ProgressBar spinner;
		private ImageGridActivity imageGridActivity = null;
		private int spinnerId;
		
		public AsyncTask<String, Void, Map<String, String>> setSpinner(int spinnerId) {
			this.spinnerId = spinnerId;
			return this;
		}
		
		public void attachActivity(ImageGridActivity imageGridActivity) {
			this.imageGridActivity = imageGridActivity;
		}
		
		public void detachActivity() {
			this.imageGridActivity = null;
		}
		
		public ProgressBar getSpinner() {
			return spinner;
		}
		
		@Override
        protected Map<String, String> doInBackground(String... params) {
            
            String url = "";
            if( params.length > 0 ){
            	url = params[0];		    	
            }
           
            ImageExtractor imageExtractor = new ImageExtractor(url);
    		
    		Map<String, String> images = null;
    		try {
    			images = imageExtractor.getImages();
    		} catch (IOException e) {
    			exc = e;
    			Log.e("catched_error", e.getMessage(), e);
    		}
			return images;
        }
        
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            setSpinnerVisible();
        }
        
        public void setSpinnerVisible() {
        	spinner = (ProgressBar) imageGridActivity.findViewById(spinnerId);
            spinner.setVisibility(View.VISIBLE);
        }
        
        @Override
        protected void onPostExecute(Map<String, String> images) {
            super.onPostExecute(images);
            spinner.setVisibility(View.GONE);
            if (exc != null) {
            	imageGridActivity.showError(exc);
    		} else {
    			imageGridActivity.initOriginalAndPreviewUrls(images);
    			
    			if (gridView == null && imageAdapter == null) {
    				initGridView();
    			} else 
    				imageGridActivity.getImageAdapter().notifyDataSetChanged();
    		}
        }
    }
	
	public ImageAdapter getImageAdapter() {
		return imageAdapter;
	}
	
	private void showError(Exception exc) {
		noConnectTextView.setText(exc.getMessage());
		noConnectTextView.setVisibility(View.VISIBLE);
	}
	
	private void initOriginalAndPreviewUrls(Map<String, String> images) {
		imageUrls.addAll(images.values());
		previewImageUrls.addAll(images.keySet());
	}
	
	private void initGridView() {
		gridView = (GridView) findViewById(R.id.gridview);
		imageAdapter = new ImageAdapter();
		gridView.setAdapter(imageAdapter);
		gridView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				startImageGalleryActivity(position);
			}
		});
		gridView.setOnScrollListener(new EndlessListListener());
		options = new DisplayImageOptions.Builder()
				.showStubImage(R.drawable.stub_image)
				.showImageForEmptyUri(R.drawable.image_for_empty_url)
				.cacheInMemory()
				.cacheOnDisc()
				.build();
	}

	@Override
	protected void onStop() {
		imageLoader.stop();
		super.onStop();
	}

	private void startImageGalleryActivity(int position) {
		Intent intent = new Intent(this, ImagePagerActivity.class);
		intent.putExtra(Extra.IMAGES, (Serializable)imageUrls);
		intent.putExtra(Extra.IMAGE_POSITION, position);
		
		startActivity(intent);
	}

	public class ImageAdapter extends BaseAdapter {
		@Override
		public int getCount() {
			return imageUrls.size();
		}

		@Override
		public Object getItem(int position) {
			return null;
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			final ImageView imageView;
			if (convertView == null) {
				imageView = (ImageView) getLayoutInflater().inflate(R.layout.item_grid_image, parent, false);
			} else {
				imageView = (ImageView) convertView;
			}

			imageLoader.displayImage(previewImageUrls.get(position), imageView, options, new SimpleImageLoadingListener() {
				@Override
				public void onLoadingComplete(Bitmap loadedImage) {
					Animation anim = AnimationUtils.loadAnimation(ImageGridActivity.this, R.anim.fade_in);
					imageView.setAnimation(anim);
					anim.start();
				}
			});

			return imageView;
		}
	}
}